/**
 * @author wujehy
 * @date 2020-5-6  上午10:51
 * @brief 对GeeJoan 的封装
 * @file GeeJoan.h
 */
#ifndef TESTPROTOBUFC_GEEJOAN_H
#define TESTPROTOBUFC_GEEJOAN_H
#if __cplusplus
extern "C" {
#endif
/**
 * @brief 操作状态码
 */
typedef enum ERRORCODE
{
    ERROR_OK = 0, ///< 操作成功
    ERROR_FAIL = -1, ///< 操作失败
} ERRORCODE;

//#define NetWorkPackageModel GeeJoan__Protocol__NetWork__NetWorkPackageModel

typedef enum NetWorkPackageModel
{
    NetWorkPackageModel_UNDEFINE = 0, ///< 未定义
    NetWorkPackageModel_AuthMod = 1, ///< Auth 模块类型
    NetWorkPackageModel_IOTMod = 2  ///< 物联网模块
} NetWorkPackageModel;

// 去掉前缀 重定义 外部类型

#define IOT_TYPE(T)             GeeJoan__Protocol__IoT__##T
#define Auth_TYPE(T)            GeeJoan__Protocol__Auth__##T
#define NetWork_TYPE(T)         GeeJoan__Protocol__NetWork__##T
/**
 * @brief 网络请求包 的重定义
 */
#define NetWorkPackageRequest   NetWork_TYPE(NetWorkPackageRequest)
/**
 * @brief 网络相应包 的重定义
 */
#define NetWorkPackageRespose   NetWork_TYPE(NetWorkPackageRespose)

// AUTH
/**
 * @brief 注册 的重定义
 */
#define RegisterAPI             Auth_TYPE(RegisterAPI)
/**
 * @brief 登录请求 的重定义
 */
#define LoginRequest            Auth_TYPE(LoginRequest)
/**
 * @brief 登录相应 的重定义
 */
#define LoginRespose            Auth_TYPE(LoginRespose)
/**
 * @brief 登出 的重定义
 */
#define LogoutAPI               Auth_TYPE(LogoutAPI)
/**
 * @brief 修改密码请求 的重定义
 */
#define ChangePasswordRequest   Auth_TYPE(ChangePasswordRequest)
/**
 * @brief 修改密码的相应 的重定义
 */
#define ChangePasswordRespose   Auth_TYPE(ChangePasswordRespose)

// IoT
/**
 * @brief 查找方向的枚举 的重定义
 */
#define FindDirectionEnum       IOT_TYPE(FindDirectionEnum)
/**
 * @brief 数据权限枚举 的重定义
 */
#define DataPermissionEnum      IOT_TYPE(DataPermissionEnum)
/**
 * @brief 查找数据请求包 的重定义
 */
#define FindSensorDataRequest   IOT_TYPE(FindSensorDataRequest)

/**
 * @brief 数据上报 的重定义
 */
#define UploadSensorDataAPI     IOT_TYPE(UploadSensorDataAPI)
#define FindSensorDataRespose   IOT_TYPE(FindSensorDataRespose)
#define SensorDataPackage       IOT_TYPE(SensorDataPackage)


#define ControlDeviceRequest    IOT_TYPE(ControlDeviceRequest)
#define ControlDeviceRespose    IOT_TYPE(ControlDeviceRespose)

#define ControlDeviceListerner  IOT_TYPE(ControlDeviceListerner)
#define ControlDeviceAckAPI     IOT_TYPE(ControlDeviceAckAPI)
#define ControlDeviceAckListerner   IOT_TYPE(ControlDeviceAckListerner)
#define LoginDeviceAPI          IOT_TYPE(LoginDeviceAPI)


// TODO 暂未封装
#define FindGatewayRequest      IOT_TYPE(FindGatewayRequest)
#define FindGatewayRespose      IOT_TYPE(FindGatewayRespose)
#define CreateDeviceRequest     IOT_TYPE(CreateDeviceRequest)
#define CreateDeviceRespose     IOT_TYPE(CreateDeviceRespose)
#define FindDevicesRequest      IOT_TYPE(FindDevicesRequest)
#define FindDeviceData          IOT_TYPE(FindDeviceData)
#define FindDevicesRespose      IOT_TYPE(FindDevicesRespose)
#define GenerateDeviceTokenRequest IOT_TYPE(GenerateDeviceTokenRequest)
#define GenerateDeviceTokenRespose IOT_TYPE(GenerateDeviceTokenRespose)
#define FindDeviceTokenRequest  IOT_TYPE(FindDeviceTokenRequest)
#define FindDeviceTokenRespose  IOT_TYPE(FindDeviceTokenRespose)

/**
 * @brief Auth 模块的子类型是sub_type
 */
enum AUTH_MOD_TYPE
{
    AUTH_REGISTER = 1, ///< 注册
    AUTH_LOGIN = 2, ///< 登录
    AUTH_LOGOUT = 3, ///< 登出
    AUTH_CHANGE_PASSWORD = 5, ///<修改密码
};

/**
 * @brief IoT 模块的 子类型是
 */
enum IOT_MOD_TYPE
{
    IOT_UPLOAD_SENSOR_DATA = 1, ///< 数据上报
    IOT_FIND_SENSOR_DATA = 2, ///< 数据查询
    IOT_CONTROL_DEVICE = 3, ///< 控制设备
    IOT_CONTROL_ACK = 4, ///< 控制确认
    IOT_CONTROL_ACK_LISTERNER = 5, ///< 控制确认监听器
    IOT_CONTROL_LISTERNER = 6, ///< 控制监听器
    IOT_LOGIN_DEVICE = 7, ///< 登录设备
    IOT_HEART_BEAT = 8, ///< 心跳包
    IOT_FIND_GATEWAY = 9, ///< 查找网关
    IOT_CREATE_DEVICE = 10, ///< 创建设备
    IOT_FIND_DEVICE_TOKEN = 11, ///< 查询设备的Token
    IOT_GENERATE_DEVICE_TOKEN = 12, ///< 生成设备的Token
};

#include "GeeJoan/NetWorkPackage.pb-c.h"
#include "GeeJoan/AuthModule.pb-c.h"
#include "GeeJoan/IoTModule.pb-c.h"

/******* NetworkPackage start *******/
//NetWorkPackageRequest
//NetWorkPackageRespose

/**
 * @author WuJeHy
 * @brief  系列化 网络请求权数据包
 * @param[out] outBuffer 序列化输出
 * @param[in] mod 模块类型
 * @param[in] sub_type 子类型
 * @param[in] taskid 任务id , 回包的时候 匹配 任务的扎id
 * @param[in] body 内容
 * @param[in] data_len 内容长度
 * @param[in] pubilckey  TODO , 填 NULL , 公钥 , 当使用端对端 加密的时候真有效
 * @param[in] pubilckey_len  填在 0 公钥长度
 * @return 返回 序列化的buff 长度 , 当着<0 的时候 错误
 */
int serialzeNetWorkPackageRequest(
        void **outBuffer,
        NetWorkPackageModel mod,
        int sub_type,
        long long taskid,
        void *body, int data_len,
        void *pubilckey, int pubilckey_len);

/**
 * @author WuJeHy
 * @brief 反序列化 网络请求包
 * @param[out] out 输出的指针 , 外部传入 , 注意释放内存
 * @param[in] buffer 网络请求包 序列化 后的 buff 指针
 * @param[in] bufferLen buff 的长度
 * @return 返回 状态 ERROR_OK -- 处理成功 , ERROR_FAIL 处理失败者
 */
ERRORCODE deserialzeNetWorkPackageRequest(
        NetWorkPackageRequest **out,
        void *buffer, int bufferLen);

/**
 * @author WuJeHy
 * @brief 释放 协议 对象的 指针
 * @param[in] type 协议的指针
 */
void free_NetWorkPackageRequest(NetWorkPackageRequest *type);

/**
 * @author WuJeHy
 * @brief 序列化 网络相应包
 * @param[out] outBuffer 序列化输出
 * @param[in] mod 模块类型
 * @param[in] sub_type 子类型
 * @param[in] taskid 任务id , 与请求包的taskid 相同或, 客户端可用于 确定 回包的上下文
 * @param[in] code 操作状态码 , 200 -- 操作成功用, 可以解包的数据包则可以解包 , code == 500 服务端错误 , body 储存在错误信息 ,
 * @param[in] body 数据体
 * @param[in] data_len 数据长度
 * @param[in] pubilckey TODO , 填 NULL , 公钥 , 当使用端对端 加密的时候真有效
 * @param[in] pubilckey_len 公钥长度
 * @return 返回 序列化的buff 长度 , 当着<0 的时候 错误
 */
int serialzeNetWorkPackageRespose(
        void **outBuffer,
        NetWorkPackageModel mod,
        int sub_type,
        long long taskid,
        int code,
        void *body, int data_len,
        void *pubilckey, int pubilckey_len);

/**
 * @author WuJeHy
 * @brief 反序列化 网络相应包
 * @param[out] out 输出的指针 , 外部传入 , 注意释放内存
 * @param[in] buffer 网络请求包 序列化 后的 buff 指针
 * @param[in] bufferLen buff 的长度
 * @return 返回 状态 ERROR_OK -- 处理成功 , ERROR_FAIL 处理失败者
 */
ERRORCODE deserialzeNetWorkPackageRespose(
        NetWorkPackageRespose **out,
        void *buffer, int bufferLen);

/**
 * @author WuJeHy
 * @brief 释放 协议 对象的 指针
 * @param[in] type 协议的指针
 */
void free_NetWorkPackageRespose(NetWorkPackageRespose *type);
/******* NetworkPackage end   *******/


/******* register start *******/

/**
 * @author WuJeHy
 * @brief 序列化 注册Api
 * @param[out] outBuffer 序列化输出
 * @param[in] username 用户名
 * @param[in] password 密码
 * @param[in] email 邮箱
 * @return
 */
int serialzeRegisterAPI(void **outBuffer, const char *username, const char *password, const char *email);

/**
 * @author WuJeHy
 * @brief 反序列化 注册Api
 * @param[out] out 序列化的输出
 * @param[in] buffer 需要序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 * @return
 */
ERRORCODE deserialzeRegisterAPI(RegisterAPI **out, void *buffer, int bufferLen);

/**
 * @author WuJeHy
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_RegisterAPI(RegisterAPI *type);
/******* register end *******/

/******* login start *******/
/**
 * @author WuJeHy
 * @brief 序列化 登录请求包
 * @param[out] outBuffer 序列化输出
 * @param[in] username 用户名
 * @param[in] password 密码
 * @param[in] timeStamp 当前的时间戳
 * @return
 */
int serialzeLoginRequest(void **outBuffer, const char *username, const char *password, long long timeStamp);

/**
 * @author WuJeHy
 * @brief  反序列化 登录请求包
 * @param[out] out 反序列化的输出
 * @param[in] buffer 需要序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 * @return
 */
ERRORCODE deserialzeLoginRequest(LoginRequest **out, void *buffer, int bufferLen);

/**
 * @author WuJeHy
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_LoginRequest(LoginRequest *type);

/**
 * @author WuJeHy
 * @param[out] outBuffer 序列化输出
 * @param[in] token
 * @return
 */
int serialzeLoginRespose(void **outBuffer, const char *token);

/**
 *
 * @param[out] out 反序列化的输出
 * @param[in] buffer 序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 */
ERRORCODE deserialzeLoginRespose(LoginRespose **out, void *buffer, int bufferLen);

/**
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_LoginRespose(LoginRespose *type);

/******* login end   *******/


/******* logout start *******/
/**
 * @author WuJeHy
 * @brief 序列化登出Api
 * @param[out] outBuffer 序列化输出
 * @param[in] token 用户的当前Token
 * @param[in] currentTime 当前时间戳
 * @return
 */
int serialzeLogoutAPI(void **outBuffer, const char *token, long long currentTime);

/**
 * @author WuJeHy
 * @brief 反序列化 登出Api 包
 * @param[out] out 序列化的输出
 * @param[in] buffer 需要序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 * @return
 */
ERRORCODE deserialzeLogoutAPI(LogoutAPI **out, void *buffer, int bufferLen);

/**
 * @author WuJeHy
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_LogoutAPI(LogoutAPI *type);

/******* logout end   *******/

/******* ChangePassword start *******/

/**
 * @author WuJeHy
 * @brief 序列化 修改密码为请求包
 * @param[out] outBuffer 序列化输出
 * @param[in] oldToken
 * @param[in] newpassword
 * @param[in] timeStamp
 * @return
 */
int serialzeChangePasswordRequest(void **outBuffer, const char *oldToken, const char *newpassword, long long timeStamp);

/**
 * @author WuJeHy
 * @brief 反序列化 修改密码请求包
 * @param[out] out 序列化的输出
 * @param[in] buffer 需要序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 * @return
 */
ERRORCODE deserialzeChangePasswordRequest(ChangePasswordRequest **out, void *buffer, int bufferLen);

/**
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_ChangePasswordRequest(ChangePasswordRequest *type);


/**
 * @author WuJeHy
 * @brief
 * @param[out] outBuffer 序列化输出
 * @param[in] newToken
 * @return
 */
int serialzeChangePasswordRespose(void **outBuffer, const char *newToken);

/**
 * @author WuJeHy
 * @brief
 * @param[out] out 序列化的输出
 * @param[in] buffer 需要序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 * @return
 */
ERRORCODE deserialzeChangePasswordRespose(ChangePasswordRespose **out, void *buffer, int bufferLen);

/**
 * @author WuJeHy
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_ChangePasswordRespose(ChangePasswordRespose *type);

/******* ChangePassword end   *******/


/******* IoTMod start *******/
/******* UploadData start *******/



/**
 * @author WuJeHy
 * @brief 序列化 上报数据
 * @param[out] outBuffer 序列化输出
 * @param[in] token
 * @param[in] GatewayId 网关id
 * @param[in] DevideId 设备 id
 * @param[in] permission
 * @param[in] key
 * @param[in] data
 * @return
 */
int serialzeUploadSensorDataAPI(
        void **outBuffer,
        const char *token,
        unsigned long long GatewayId,
        unsigned long long DevideId,
        DataPermissionEnum permission,
        int key, const char *data);

/**
 *
 * @param[out] out 序列化的输出
 * @param[in] buffer 需要序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 * @return
 */
ERRORCODE deserialzeUploadSensorDataAPI(UploadSensorDataAPI **out, void *buffer, int bufferLen);

/**
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_UploadSensorDataAPI(UploadSensorDataAPI *type);
/******* UploadData end   *******/

/******* FindData start *******/\
/**
 *
 * @param[out]  outBuffer
 * @param[in] token
 * @param[in] GatewayId
 * @param[in] DevideId
 * @param[in] key
 * @param[in] time
 * @param[in] direction
 * @param[in] size
 * @return
 */
int serialzeFindSensorDataRequest(
        void **outBuffer,
        const char *token,
        unsigned long long GatewayId,
        unsigned long long DevideId,
        int key,
        long long time,
        FindDirectionEnum direction,
        int size);

/**
 *
 * @param[out] out 序列化的输出
 * @param[in] buffer 需要序列化的buffer指针
 * @param[in] bufferLen buffer 的长度
 * @return 返回执行结果 , ERROR_OK -- 执行成功用, ERROR_FAIL -- 执行失败
 * @return
 */
ERRORCODE
deserialzeFindSensorDataRequest(FindSensorDataRequest **out, void *buffer, int bufferLen);

/**
 * @brief 释放 内存
 * @param[in] type 需要释放的类型的指针
 */
void free_FindSensorDataRequest(FindSensorDataRequest *type);

int initSensorDataPackages(SensorDataPackage datas[], int size);
int serialzeFindSensorDataRespose(
        void **outBuffer,
        unsigned long long GatewayId,
        unsigned long long DevideId,
        SensorDataPackage datas[],
        int datasize);
ERRORCODE deserialzeFindSensorDataRespose(FindSensorDataRespose **out, void *buffer, int bufferLen);
void free_FindSensorDataRespose(FindSensorDataRespose *type);

/******* FindData end   *******/
/******* ControlDeviceRequest start   *******/

int serialzeControlDeviceRequest(
        void **outBuffer, const char* token,
        unsigned long long GatewayId,
        unsigned long long DevideId,
        const char* data);
ERRORCODE deserialzeControlDeviceRequest(ControlDeviceRequest **out, void *buffer, int bufferLen);
void free_ControlDeviceRequest(ControlDeviceRequest *type);
/******* ControlDeviceRequest end   *******/

/******* ControlDeviceRespose start *******/
int serialzeControlDeviceRespose(
        void **outBuffer, const char* taskCode,
        long long time
        );
ERRORCODE deserialzeControlDeviceRespose(ControlDeviceRespose **out, void *buffer, int bufferLen);
void free_ControlDeviceRespose(ControlDeviceRespose *type);
/******* ControlDeviceRespose end   *******/

/******* ControlDeviceListerner start *******/
int serialzeControlDeviceListerner(
        void **outBuffer,
        const char* taskCode,
        const char* data,
        long long time
);
ERRORCODE deserialzeControlDeviceListerner(ControlDeviceListerner **out, void *buffer, int bufferLen);
void free_ControlDeviceListerner(ControlDeviceListerner *type);
/******* ControlDeviceListerner end   *******/

/******* ControlDeviceListerner start *******/
int serialzeControlDeviceAckAPI(
        void **outBuffer,
        const char* token,
        const char* taskCode,
        int errCode,
        const char* errorMsg
);
ERRORCODE deserialzeControlDeviceAckAPI(ControlDeviceAckAPI **out, void *buffer, int bufferLen);
void free_ControlDeviceAckAPI(ControlDeviceAckAPI *type);
/******* ControlDeviceListerner end   *******/


/******* ControlDeviceListerner start *******/
int serialzeControlDeviceAckListerner(
        void **outBuffer,
        const char* taskCode,
        int errCode,
        const char* errorMsg,
        long long time
);
ERRORCODE deserialzeControlDeviceAckListerner(ControlDeviceAckListerner **out, void *buffer, int bufferLen);
void free_ControlDeviceAckListerner(ControlDeviceAckListerner *type);
/******* ControlDeviceListerner end   *******/


/******* IoTMod end   *******/

int HexString2Char(void **outData, const char *data, int len);

#if __cplusplus
};
#endif
#endif //TESTPROTOBUFC_GEEJOAN_H
